﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

	<head>
		<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
		<title>Setting Management - 设置管理</title>
		<link type="text/css" rel="stylesheet" href="bootstrap.min.css" />
	</head>

	<body>

		<div class="document-contents">

			<h3 id="DocIntroduction">Introduction - 介绍</h3>
			<p>Every application need to store some settings and use these settings in 
somewhere in the application. ASP.NET Boilerplate provides a strong 
infrastructure to store/retrieve <strong>application</strong>, <strong>tenant
				</strong>and <strong>user</strong> level settings usable both in <strong>server
				</strong>and <strong>client </strong>sides.</p>
			<p class="translation">
				每个应用程序都需要存储一些设置，并在应用程序听某些地方使用这些设置。
				ASP.NET Boilerplate 提供了一个强大的基础设施来存储/检索<strong>应用程序</strong>，<strong>租户</strong>及<strong>用户</strong>级别的设置，可同时运用于<strong>服务器</strong>和<strong>客户端</strong>。
			</p>
			<p>A setting is a <strong>name-value string</strong> pair that is generally 
stored in a database (or another source). We can store non-string values by 
converting to string.</p>
			<p class="translation">
				一个设置通常是存储在数据库（或其它源）中的<strong>名称-值字符串</strong>对。我们可以通过把非字符串值转换成字符串来存储非字符串值。
			</p>

			<div class="bs-callout bs-callout-warning">
				<h4>About ISettingStore - 关于 ISettingStore</h4>
				<p>
					<strong>ISettingStore</strong> 
interface must be implemented in order to use setting system. While you can 
implement it in your own way, it's fully implemented in <strong>module-zero</strong> 
project. If it's not implemented, settings are read from application's <strong>
configuration file</strong> (web.config or app.config) but can not change any 
setting. Also, scoping will not work.</p>
				<p claas="translation">
					为了使用设置系统必须实现 <strong>ISettingStore</strong> 接口。虽然你可以用自己的方式来实现它，但 <strong>module-zero</strong> 项目中已有完整的实现。
					如果它没有被实现，设置从应用程序的<strong>配置文件</strong>（web.config 或 app.config）读取，但不能改变任何设置。
					此外，范围将不起作用。
				</p>
			</div>

			<h3 id="DocDefiningSettings">Defining settings - 定义设置</h3>
			<p>A setting must be defined before usage. ASP.NET Boilerplate is designed to be 
				<a href="/Module-System.html">modular</a>. So, different modules can have different settings. A module should 
create a class derived from <strong>SettingProvider </strong>in order to define it's settings. 
An example setting provider is shown below:</p>
			<p class="translation">
				一个设置必须在使用前被定义。ASP.NET Boilerplate 是<a href="/Module-System.html">模块化</a>设计的。
				因此，不同的模块可以拥有不同的设置。为了定义模块的设置，模块应该创建一个从 <strong>SettingProvider</strong> 派生的类。
				以下是一个设置提供者的例子：
			</p>
			<pre lang="cs">public class MySettingProvider : SettingProvider
{
    public override IEnumerable&lt;SettingDefinition&gt; GetSettingDefinitions(SettingDefinitionProviderContext context)
    {
        return new[]
                {
                    new SettingDefinition(
                        &quot;SmtpServerAddress&quot;,
                        &quot;127.0.0.1&quot;
                        ),

                    new SettingDefinition(
                        &quot;PassiveUsersCanNotLogin&quot;,
                        &quot;true&quot;,
                        scopes: SettingScopes.Application | SettingScopes.Tenant
                        ),

                    new SettingDefinition(
                        &quot;SiteColorPreference&quot;,
                        &quot;red&quot;,
                        scopes: SettingScopes.User,
                        isVisibleToClients: true
                        )

                };
    }
}</pre>
			<p>
				<strong>GetSettingDefinitions</strong> method should return <strong>
SettingDefinition</strong> objects. SettingDefinition class has some 
parameters in it's constructor:</p>
			<p class="translation">
				<strong>GetSettingDefinitions</strong> 方法应该返回 <strong>SettingDefinition</strong> 对象。
				SettingDefinition 类在它的构造函数中拥有一些参数：
			</p>
			<ul>
				<li>
					<strong>Name </strong>(required): A setting must have a 
	system-wide <strong>unique </strong>name. It's good idea to define a const 
	string for a setting name instead of a magic string.</li>
				<p class="translation">
					<strong>Name </strong>（必需）：一个设置必须在全系统范围内拥有<strong>唯一</strong>的名称。
					一个好主意是为设置名称定义一个常量字符串而不是使用魔术字符串。
				</p>
				<li>
					<strong>Default value</strong>: A setting may have a default value. This 
	value can be null or empty string.</li>
				<li class="translation">
					<strong>Default value</strong>：一个设置可以拥有一个默认值。这个值可以是空引用或空字符串。
				</li>
				<li>
					<strong>Scopes</strong>: A setting should define it's scope (see below).</li>
				<p class="translation">
					<strong>Scopes</strong>：一个设置应该定义它的范围（见下文）。
				</p>
				<li>
					<strong>Display name</strong>: A localizable string that can be used to 
	show setting's name later in UI.</li>
				<p class="translation">
					<strong>Display name</strong>：一个本地化字符串，可以被用于 UI 层设置名称的显示。
				</p>
				<li>
					<strong>Description</strong>: A localizable string that can be used to 
	show setting's description later in UI.</li>
				<p class="translation">
					<strong>Description</strong>：一个本地化字符串，可以被用于 UI 层设置描述的显示。
				</p>
				<li>
					<strong>Group</strong>: Can be used to group settings. This is just for 
	UI, not used in setting management.</li>
				<p class="translation">
					<strong>Group</strong>：可以被用于组设置。这仅用于用户界面，不能在设置管理中使用。
				</p>
				<li>
					<strong>IsVisibleToClients</strong>: Set true to make a setting usable 
	on the client side.</li>
				<p class="translation">
					<strong>IsVisibleToClients</strong>：设置为 true，使用一个设置在客户端可用。
				</p>
				<li>
					<strong>isInherited</strong>: Used to set if this setting is 
					inherited by tenant and users (See setting scope section).</li>
				<p class="translation">
					<strong>isInherited</strong>：指示这个设置是否是从租户和用户继承的（参阅设置范围节）。
				</p>
				<li>
					<strong>customData</strong>: Can be used to set a custom 
					data for this setting definition.</li>
				<p class="translation">
					<strong>customData</strong>：可以用于为这个设置定义设置一个自定义数据。
				</p>
			</ul>
			<p>After creating a setting provider, we should register it in PreIntialize 
method of our module:</p>
			<p class="translation">
				在创建了设置提供者之后，我们应该在模块的 PreIntialize 中注册它。
			</p>
			<pre lang="cs">Configuration.Settings.Providers.Add&lt;MySettingProvider&gt;();</pre>
			<p>Setting providers are registered to
				<a href="/Dependency-Injection.html">dependency injection</a> 
automatically. So, a setting provider can inject any dependency (like a 
repository) to build setting definitions using some other sources.</p>
			<p class="translation">
				设置提供者是被自动注册到<a href="/Dependency-Injection.html">依赖注入</a>中。因此，一个设置提供者可以注入任何依赖（如仓库）来使用其它源来生成设置定义。
			</p>
			<h4 id="DocSettingScopes">Setting scope - 设置范围</h4>
			<p>&nbsp;There are three <strong>setting scopes</strong> (or levels) 
defined in <strong>SettingScopes</strong> enum:</p>
			<p class="translation">
				在 <strong>SettingScopes</strong> 枚举中定义了三种<strong>设置范围</strong>（或级别）：
			</p>
			<ul>
				<li>
					<strong>Application</strong>: An application scoped setting is used for 
	user/tenant independed settings. For example, we can define a setting named 
	"SmtpServerAddress" to get server's IP address when sending emails. If this 
	setting has a single value (not changes based on users), then we can define 
	it as Application scoped.</li>
				<p class="translation">
					<strong>Application</strong>：被用于应用程序范围的设置，对于用户/租户的独立设置。
					例如，我们可以定义一个叫做 “SmtpServerAddress”的设置，用在当发送邮件时获取服务器 IP 地址。
					如果这个设置拥有一个单一的值（不依赖于用户改变），那么我们可以作为应用程序范围来定义它。
				</p>
				<li>
					<strong>Tenant</strong>: If the application is multi-tenant, we can 
	define tenant-specific settings.</li>
				<p class="translation">
					<strong>Tenant</strong>：如果应用程序是多租户的，我们定义特定于租户的设置。
				</p>
				<li>
					<strong>User</strong>: We can use a user scoped setting to store/get 
	value of the setting specific to each user.</li>
				<p class="translation">
					<strong>User</strong>：我们可以使用用户范围设置来存储/获取特定于每个用户设置的值。
				</p>
			</ul>
			<p>SettingScopes enum has <strong>Flags </strong>attribute, so we can define a 
setting with <strong>more than one scopes</strong>.</p>
			<p class="translation">
				SettingScopes 拥有 Flags 特性，因此我们可以定义设置拥有多个范围。
			</p>
			<p>Setting scope is <strong>hierarchic</strong> by default (unless 
			you set <strong>isInherited</strong> to false). For example, if we define a 
setting's scope as "Application | Tenant | User" and try to get <strong>current value 
				</strong>of the the 
setting;</p>
			<p class="translation">
				设置范围默认是<strong>层次化</strong>的（除非你设置 <strong>isInherited</strong> 为假）。
				例如，如果我们定义了一个像“Application | Tenant | User”的设置范围，并尝试获取这个设置的<strong>当前值</strong>：
			</p>
			<ul>
				<li>We get the user-specific value if it's defined (overrided) for the user.</li>
				<p class="translation">如果它是为用户定义（重写）的，我们将得到特定于用户的值。</p>
				<li>If not, we get the tenant-specific value if it's defined (overrided) for the tenant.</li>
				<p class="translation">否则，如果它是为租户定义（重写）的，我们将得到特定于租户的值。</p>
				<li>If not, we get the application value if it's defined.</li>
				<p class="translation">否则，如果它已被定义的，我们将得到用于应用程序的值。</p>
				<li>If not, we get the <strong>default value</strong>.</li>
				<p class="translation">否则，我们将得到<strong>默认值</strong>。</p>
			</ul>
			<p>Default value can be <strong>null </strong>or <strong>empty </strong>string. 
It's adviced to provide default values for settings where it's possible.</p>
			<p class="translation">
				默认值可以是<strong>空引用</strong>或<strong>空字符串</strong>。如果可能建议为设置提供一个默认值。
			</p>
			<h4>Overriding Setting Definitions - 重写设置定义</h4>
			<p>context.Manager can be used to get a setting definition to change 
			it's values. In this way, you can manipulate setting definitions of
			<a href="/Module-System.html">depended modules</a>.</p>
			<p class="translation">
				context.Manager 可以用于获取一个设置定义及修改该设置的值。
				在这种方法中，你可以控制<a href="/Module-System.html">依赖模块</a>中的设置定义。
			</p>

			<h3 id="DocGettingValues">Getting setting values - 获取设置值</h3>
			<p>After defining a setting, we can get it's current value both in server and 
client.</p>
			<p class="translation">定义了一个设置后，我们可以在服务器或客户端中获取它的当前值。</p>
			<h4 id="DocGettingValuesServer">Server side - 服务器端</h4>
			<p>
				<strong>ISettingManager </strong>is used to perform setting 
operations. We can inject and use it anywhere in the application. 
ISettingManager defines many methods to get a setting's value.</p>
			<p class="translation">
				<strong>ISettingManager</strong> 被用来执行设置操作。我们可以在应用程序中的任何位置注入并使用它。ISettingManager 定义了一些方法来获取设置的值。
			</p>
			<p>Most used method is <strong>GetSettingValue </strong>(or GetSettingValueAsync 
for async call). It returns <strong>current value </strong>of the setting based 
on default value, application, tenant and user settings (as described in Setting 
scope section before). Examples:</p>
			<p class="translation">
				最常用的方法是 <strong>GetSettingValue</strong>（或 GetSettingValueAsync，用于异步调用）。
				它返回设置的<strong>当前值</strong>，这个值是基于默认值，应用程序，租户和用户设置（见设置范围节之前的描述）。
				例如：
			</p>
			<pre lang="cs">//Getting a boolean value (async call)
var value1 = await SettingManager.GetSettingValueAsync&lt;bool&gt;(&quot;PassiveUsersCanNotLogin&quot;);

//Getting a string value (sync call)
var value2 = SettingManager.GetSettingValue(&quot;SmtpServerAddress&quot;);
			</pre>
			<p>GetSettingValue has generic and async versions as shown above. There are also methods to get a specific tenant or user's setting value or 
list of all setting values.</p>
			<p class="translation">
				如上所述，GetSettingValue 拥有泛型和异步版本。还有一些方法用于获取特定租户或用户的设置值，获取所有设置值的列表。
			</p>
			<p>Since ISettingManager is widely used, some special <strong>base classes</strong> (like 
ApplicationService, DomainService and AbpController) has a property named
				<strong>SettingManager</strong>. If we derived from these classes, no need to 
explicitly inject it.</p>
			<p class="translation">
				由于 ISettingManager 是被广泛使用的，所以一些特殊的基类（像 ApplicationService，DomainService，AbpController）拥有一个命名为 SettingManager 的属性。
				如果我们是从这些类派生的，就不需要明确注入它。
			</p>
			<h4 id="DocGettingValuesClient">Client side - 客户端</h4>
			<p>If you set <strong>IsVisibleToClients</strong> as true while defining a 
setting, then you can get it's current value in the client side using 
javascript. <strong>abp.setting</strong> namespace defines needed functions and 
objects. Example:</p>
			<p class="translation">
				如果当你定义一个设置时将 <strong>IsVisibleToClients</strong> 设置为真，
				那么你可以使用 javascript 在客户端获取它的当前值。
				<strong>abp.setting</strong> 命名空间定义了需要的函数和对象。
			</p>
			<pre lang="js">var currentColor = abp.setting.get("SiteColorPreference");</pre>
			<p>There is also <strong>getInt</strong> and <strong>getBoolean</strong> methods. You can get all values using 
				<strong>abp.setting.values</strong> object. Note that; If you change a setting in server side, clienct can not know this change unless 
page is refreshed, settings are somehow reloaded or it's manually updated by 
code.</p>
			<p class="translation">
				还有 <strong>getInt</strong> 和 <strong>getBoolean</strong> 方法。你可以使用 <strong>abp.setting.values</strong> 对象来获取全部值。
				注意；如果在服务器端修改了一个设置，客户端是不知道这个变化，除非刷新页面，设置重新加载或通过代码手动更新。
			</p>
			<h3 id="DocChangeSettings">Changing settings - 修改设置</h3>
			<p>ISettingManager defines <strong>ChangeSettingForApplicationAsync</strong>, 
				<strong>ChangeSettingForTenantAsync</strong> and 
				<strong>ChangeSettingForUserAsync </strong>methods (and sync versions) to change settings for 
the application, for a 
tenant and for a user respectively.</p>
			<p class="translation">
				ISettingManager 定义了 <strong>ChangeSettingForApplicationAsync</strong>, 
				<strong>ChangeSettingForTenantAsync</strong> 和 <strong>ChangeSettingForUserAsync </strong> 方法（及其异步版本）
				来分别为应用程序，租户和用户修改设置。
			</p>
			<h3 id="DocCaching">About caching - 关于缓存</h3>

			<p>Setting Manager caches settings on the server side. So, we should not directly change 
a setting value using repository or database update query.</p>
			<p class="translation">
				设置管理器缓存设置在服务器端。因此，我们不应该直接使用仓库或数据库更新查询来修改一个设置值。
			</p>
		</div>
	</body>

</html>
